<?php

use Psr\Http\Message\ResponseInterface;
use Yansongda\Pay\Pay;
// 返回数组
use Yansongda\Pay\Contract\ParserInterface;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Parser\ArrayParser;
use Yansongda\Supports\Collection;

class Payment
{
  protected $config = [
    'alipay' => [
      'default' => [
        // 必填-支付宝分配的 app_id
        'app_id' => '2016082000295641',
        // 必填-应用私钥 字符串或路径
        // 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
        'app_secret_cert' => 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDRjOg5DnX+8L+rB8d2MbrQ30Z7JPM4hiDhawHSwQCQ7RlmQNpl6b/N6IrPLcPFC1uii179U5Il5xTZynfjkUyJjnHusqnmHskftLJDKkmGbSUFMAlOv+NlpUWMJ2A+VUopl+9FLyqcV+XgbaWizxU3LsTtt64v89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhDkFPxeBxHbfwppsul+DYUyTCcl0Ltbga/mUechk5BksW6yPPwprYHQBXyM16Jc3q5HbNxh3660FyvUBFLuVWIBs6RtR2gZCa6b8rOtCkPQKhUKvzRMlgheOowXsWdk99GjxGQDK5W4XAgMBAAECggEAYPKnjlr+nRPBnnNfR5ugzH67FToyrU0M7ZT6xygPfdyijaXDb2ggXLupeGUOjIRKSSijDrjLZ7EQMkguFHvtfmvcoDTDFaL2zq0a3oALK6gwRGxOuzAnK1naINkmeOmqiqrUab+21emEv098mRGbLNEXGCgltCtz7SiRdo/pgIPZ1wHj4MH0b0K2bFG3xwr51EyaLXKYH4j6w9YAXXsTdvzcJ+eRE0Yq4uGPfkziqg8d0xXSEt90HmCGHKo4O2eh1w1IlBcHfK0F6vkeUAtrtAV01MU2bNoRU147vKFxjDOVBlY1nIZY/drsbiPMuAfSsodL0hJxGSYivbKTX4CWgQKBgQDd0MkF5AIPPdFC+fhWdNclePRw4gUkBwPTIUljMP4o+MhJNrHp0sEy0sr1mzYsOT4J20hsbw/qTnMKGdgy784bySf6/CC7lv2hHp0wyS3Es0DRJuN+aTyyONOKGvQqd8gvuQtuYJy+hkIoHygjvC3TKndX1v66f9vCr/7TS0QPywKBgQCXgVHERHP+CarSAEDG6bzI878/5yqyJVlUeVMG5OXdlwCl0GAAl4mDvfqweUawSVFE7qiSqy3Eaok8KHkYcoRlQmAefHg/C8t2PNFfNrANDdDB99f7UhqhXTdBA6DPyW02eKIaBcXjZ7jEXZzA41a/zxZydKgHvz4pUq1BdbU5ZQKBgHyqGCDgaavpQVAUL1df6X8dALzkuqDp9GNXxOgjo+ShFefX/pv8oCqRQBJTflnSfiSKAqU2skosdwlJRzIxhrQlFPxBcaAcl0VTcGL33mo7mIU0Bw2H1d4QhAuNZIbttSvlIyCQ2edWi54DDMswusyAhHxwz88/huJfiad1GLaLAoGASIweMVNuD5lleMWyPw2x3rAJRnpVUZTc37xw6340LBWgs8XCEsZ9jN4t6s9H8CZLiiyWABWEBufU6z+eLPy5NRvBlxeXJOlq9iVNRMCVMMsKybb6b1fzdI2EZdds69LSPyEozjkxdyE1sqH468xwv8xUPV5rD7qd83+pgwzwSJkCgYBrRV0OZmicfVJ7RqbWyneBG03r7ziA0WTcLdRWDnOujQ9orhrkm+EY2evhLEkkF6TOYv4QFBGSHfGJ0SwD7ghbCQC/8oBvNvuQiPWI8B+00LwyxXNrkFOxy7UfIUdUmLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==',
        // 必填-应用公钥证书 路径
        // 设置应用私钥后，即可下载得到以下3个证书
        'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
        // 必填-支付宝公钥证书 路径
        'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
        // 必填-支付宝根证书 路径
        'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
        'return_url' => $GLOBALS['cms']['domain'] . '/alipay/return',
        'notify_url' => $GLOBALS['cms']['domain'] . '/alipay/notify',
        // 选填-第三方应用授权token
        'app_auth_token' => '',
        // 选填-服务商模式下的服务商 id，当 mode 为 Pay::MODE_SERVICE 时使用该参数
        'service_provider_id' => '',
        // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
        'mode' => Pay::MODE_NORMAL,
      ]
    ],
    'wechat' => [
      'default' => [
        // 必填-商户号，服务商模式下为服务商商户号
        // 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
        'mch_id' => '1535175401',
        // 必填-商户秘钥
        // 即 API v3 密钥(32字节，形如md5值)，可在 账户中心->API安全 中设置
        'mch_secret_key' => 'N3BPHU8AS4tJKwIAzyvi6WzCfB2Qy6yI',
        // 必填-商户私钥 字符串或路径
        // 即 API证书 PRIVATE KEY，可在 账户中心->API安全->申请API证书 里获得
        // 文件名形如：apiclient_key.pem
        'mch_secret_cert' => '',
        // 必填-商户公钥证书路径
        // 即 API证书 CERTIFICATE，可在 账户中心->API安全->申请API证书 里获得
        // 文件名形如：apiclient_cert.pem
        'mch_public_cert_path' => '',
        // 必填-微信回调url
        // 不能有参数，如?号，空格等，否则会无法正确回调
        'notify_url' => $GLOBALS['cms']['domain'] . '/wechat/notify',
        // 选填-公众号 的 app_id
        // 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
        'mp_app_id' => 'wx180e49aa1c02b268',
        // 选填-小程序 的 app_id
        'mini_app_id' => '',
        // 选填-app 的 app_id
        'app_id' => '',
        // 选填-合单 app_id
        'combine_app_id' => '',
        // 选填-合单商户号
        'combine_mch_id' => '',
        // 选填-服务商模式下，子公众号 的 app_id
        'sub_mp_app_id' => '',
        // 选填-服务商模式下，子 app 的 app_id
        'sub_app_id' => '',
        // 选填-服务商模式下，子小程序 的 app_id
        'sub_mini_app_id' => '',
        // 选填-服务商模式下，子商户id
        'sub_mch_id' => '',
        // 选填-微信平台公钥证书路径, optional，强烈建议 php-fpm 模式下配置此参数
        'wechat_public_cert_path' => [
          '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__ . '/Cert/wechatPublicKey.crt',
        ],
        // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
        'mode' => Pay::MODE_NORMAL,
      ]
    ],
    'unipay' => [
      'default' => [
        // 必填-商户号
        'mch_id' => '777290058167151',
        // 必填-商户公私钥
        'mch_cert_path' => __DIR__ . '/Cert/unipayAppCert.pfx',
        // 必填-商户公私钥密码
        'mch_cert_password' => '000000',
        // 必填-银联公钥证书路径
        'unipay_public_cert_path' => __DIR__ . '/Cert/unipayCertPublicKey.cer',
        // 必填
        'return_url' => $GLOBALS['cms']['domain'] . '/unipay/return',
        // 必填
        'notify_url' => $GLOBALS['cms']['domain'] . '/unipay/notify',
      ],
    ],
    'logger' => [
      'enable' => true,
      // 'file' => './log/pay.log',
      'file' => ROOT_PATH . 'static/log/pay.log',
      'level' => 'debug', // 建议生产环境等级调整为 info，开发环境为 debug
      // 'type' => 'single', // optional, 可选 daily.
      'type' => 'daily', // optional, 可选 daily.
      'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
    ],
    'http' => [ // optional
      'timeout' => 5.0,
      'connect_timeout' => 5.0,
      // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
  ];

  function __construct()
  {
    Pay::config($this->config);
    // 返回数组
    Pay::set(ParserInterface::class, ArrayParser::class);
  }

  /**
   * alipay
   */
  public function alipayTest()
  {
    // Pay::config($this->config);
    // 注意返回类型为 Response，具体见详细文档
    $res = Pay::alipay()->wap([
      'out_trade_no' => time(),
      'total_amount' => '0.01',
      'subject' => '测试 - 01',
      'quit_url' => SITE_DOMAIN,
    ]);
    return $res;
  }
  /**
   * alipayPayWeb
   * @param mixed $data [ 'out_trade_no' => '' . time(), 'total_amount' => '0.01', 'subject' => 'yansongda 测试 - 1', ]
   * get [ 'out_trade_no' => ''.time(), 'total_amount' => '0.01', 'subject' => 'yansongda 测试 - 1', '_method' => 'get', ]
   * @return ResponseInterface
   */
  public function alipayPayWeb($data)
  {
    // Pay::config($this->config);

    // 注意返回类型为 Response，具体见详细文档
    $res = Pay::alipay()->web($data);
    return $res;
    // 如果想获取跳转代码（表单形式），可以使用如下代码（详情请自行了解 PSR 规范）
    // $res = Pay::alipay()->web([
    //     'out_trade_no' => ''.time(),
    //     'total_amount' => '0.01',
    //     'subject' => 'yansongda 测试 - 1',
    // ]);

    // return (string) $res->getBody();
  }
  /**
   * alipayPayWap
   * @param mixed $data [ 'out_trade_no' => time(), 'total_amount' => '0.01', 'subject' => 'yansongda 测试 - 01', 'quit_url' => 'https://yansongda.cn', ]
   * get方式 [ 'out_trade_no' => ''.time(), 'total_amount' => '0.01', 'subject' => 'yansongda 测试 - 1', '_method' => 'get', ]
   * @return ResponseInterface
   */
  public function alipayPayWap($data)
  {
    // Pay::config($this->config);
    // 注意返回类型为 Response，具体见详细文档
    $res = Pay::alipay()->wap($data);
    return $res;
  }
  /**
   * alipayPayScan
   * @param mixed $data [ 'out_trade_no' => time(), 'total_amount' => '0.01', 'subject' => 'yansongda 测试 - 01', ]
   * @return qrcode url
   */
  public function alipayPayScan($data)
  {
    // Pay::config($this->config);
    $res = Pay::alipay()->scan($data);
    return $res->qr_code; // 二维码 url
  }
  /**
   * alipayQueryOrder
   * @param string/array $data [ 'out_trade_no' => '1514027114', ]
   * '1514027114'
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function alipayQueryOrder($data)
  {
    $res = Pay::alipay()->find($data);
    return $res;
  }
  /**
   * alipayQueryOrderRefund
   * @param array $data [ 'out_trade_no' => '1514027114', 'out_request_no' => '1514027114', '_type' => 'refund', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function alipayQueryOrderRefund($data)
  {
    $res = Pay::alipay()->find($data);
    return $res;
  }
  /**
   * alipayRefund
   * @param mixed $data [ 'out_trade_no' => '1623160012', 'refund_amount' => '0.01', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function alipayRefund($data)
  {
    $res = Pay::alipay()->refund($data);
    return $res;
  }
  /**
   * alipayClose
   * @param string/array $data [ 'out_trade_no' => '1623161325', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function alipayClose($data)
  {
    $res = Pay::alipay()->close($data);
    return $res;
  }
  /**
   * alipayCancel
   * @param string/array $data [ 'out_trade_no' => '1514027114', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function alipayCancel($data)
  {
    $res = Pay::alipay()->cancel($data);
    return $res;
  }

  public function alipayReturnCallback()
  {
    // Pay::config($this->config);
    $res = Pay::alipay()->callback(); // 是的，验签就这么简单！
    return $res;

    // 订单号：$data->out_trade_no
    // 支付宝交易号：$data->trade_no
    // 订单总金额：$data->total_amount
  }

  public function alipayNotifyCallback()
  {
    // Pay::config($this->config);

    /*
    try {
      $callback = Pay::alipay()->callback();
      // 请自行对 trade_status 进行判断及其它逻辑进行判断，在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功。
      // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号；
      // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）；
      // 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）；
      // 4、验证app_id是否为该商户本身。
      // 5、其它业务逻辑情况
    } catch (\Exception $e) {
      // $e->getMessage();
    }
    */

    $res = Pay::alipay()->success();
    return $res;
  }

  /**
   * wechat
   */
  public function wechatTest()
  {
    // Pay::config($this->config);
    $order = [
      'out_trade_no' => time() . '',
      'description' => 'subject-测试',
      'amount' => [
        'total' => 0.01,
      ],
      'scene_info' => [
        // 'payer_client_ip' => '1.2.4.8',
        'payer_client_ip' => get_ip(),
        'h5_info' => [
          'type' => 'Wap',
        ]
      ],
    ];

    $res = Pay::wechat()->wap($order);
    return $res;

    // $pay->appId
    // $pay->timeStamp
    // $pay->nonceStr
    // $pay->package
    // $pay->signType
  }
  /**
   * wechatPayWap
   * @param array $data [ 'out_trade_no' => time() . '', 'description' => 'subject-测试', 'amount' => [ 'total' => 1, ], 'scene_info' => [ 'payer_client_ip' => '1.2.4.8', 'h5_info' => [ 'type' => 'Wap', ] ], ]
   * @return Collection
   */
  public function wechatPayWap($data)
  {
    // Pay::config($this->config);

    $res = Pay::wechat()->wap($data);
    return $res;

    // $pay->appId
    // $pay->timeStamp
    // $pay->nonceStr
    // $pay->package
    // $pay->signType
  }
  /**
   * wechatPayScan
   * @param array $data [ 'out_trade_no' => time().'', 'description' => 'subject-测试', 'amount' => [ 'total' => 1, ], ]
   * @return qrcode url
   */
  public function wechatPayScan($data)
  {
    // Pay::config($this->config);

    $res = Pay::wechat()->scan($data);
    return $res->code_url; // 二维码内容： $qr = $res->code_url;
  }
  /**
   * wechatQueryOrder
   * @param string/array $data [ 'transaction_id' => '1217752501201407033233368018', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatQueryOrder($data)
  {
    $res = Pay::wechat()->find($data);
    return $res;
  }
  /**
   * wechatQueryOrderRefund
   * @param array $data [ 'transaction_id' => '1217752501201407033233368018', '_type' => 'refund' ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatQueryOrderRefund($data)
  {
    $res = Pay::wechat()->find($data);
    return $res;
  }
  /**
   * wechatQueryOrderCombine
   * @param array $data [ 'transaction_id' => '1217752501201407033233368018', '_type' => 'combine', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatQueryOrderCombine($data)
  {
    $res = Pay::wechat()->find($data);
    return $res;

    /*
    $order = [
      'combine_out_trade_no' => '1217752501201407033233368018',
    ];
    */
  }
  /**
   * wechatRefund
   * @param array $data [ 'out_trade_no' => '1514192025', 'out_refund_no' => time(), 'amount' => [ 'refund' => 1, 'total' => 1, 'currency' => 'CNY', ], ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatRefund($data)
  {
    $res = Pay::wechat()->refund($data);
    return $res;
  }
  /**
   * wechatClose
   * @param string/array $data [ 'out_trade_no' => '1514027114', ]
   * @return array|Collection|void
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatClose($data)
  {
    $res = Pay::wechat()->close($data);
    return $res;
  }
  /**
   * wechatCloseCombine
   * @param array $data [ 'combine_out_trade_no' => '1514027114', 'sub_orders' => '123456' ]
   * @return array|Collection|void
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatCloseCombine($data)
  {
    $res = Pay::wechat()->close($data);
    return $res;

    //$order = [
    //    'out_trade_no' => '1514027114',
    //    'sub_orders' => '123456',
    //    '_type' => 'combine',
    //];
  }
  /**
   * wechatCancel
   * @param array $data [ 'combine_out_trade_no' => '1514027114', 'sub_orders' => '123456' ]
   * @return void
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatCancel($data)
  {
    $this->wechatClose($data);
  }
  /**
   * wechatCancelCombine
   * @param array $data [ 'combine_out_trade_no' => '1514027114', 'sub_orders' => '123456' ]
   * @return void
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function wechatCancelCombine($data)
  {
    $this->wechatCloseCombine($data);
  }

  public function wechatReturnCallback()
  {
    $res = Pay::wechat()->callback();
    return $res;
  }

  public function wechatNotifyCallback()
  {
    /*
    try {
      $callback = Pay::wechat()->callback(); // 是的，验签就这么简单！
    } catch (\Exception $e) {
      // $e->getMessage();
    }
    */

    $res = Pay::wechat()->success();
    return $res;
  }

  /**
   * unipay
   */
  public function unipayTest()
  {
    // Pay::config($this->config);

    $res = Pay::unipay()->wap([
      'txnTime' => date('YmdHis'),
      'txnAmt' => 1,
      'orderId' => date('YmdHis'),
    ]);
    return $res;
  }
  /**
   * unipayPayWeb
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => date('YmdHis'), ]
   * @return mixed
   */
  public function unipayPayWeb($data)
  {
    // Pay::config($this->config);

    $res = Pay::unipay()->web($data);
    return $res;
  }
  /**
   * unipayPayWap
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => 'yansongda'.date('YmdHis'), ]
   * @return mixed
   */
  public function unipayPayWap($data)
  {
    // Pay::config($this->config);

    $res = Pay::unipay()->wap($data);
    return $res;
  }
  /**
   * unipayPayScan
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => 'scan'.date('YmdHis'), // '_type' => 'pre_auth', // 预授权 // '_type' => 'pre_order', // 统一下单 // '_type' => 'fee', // 缴费二维码 ]
   * @return qrcode url
   */
  public function unipayPayScan($data)
  {
    // Pay::config($this->config);

    $res = Pay::unipay()->wap($data);
    return $res->qrCode; // 二维码 url
  }
  /**
   * unipayQueryOrder
   * @param array $data [ 'txnTime' => '20220911041647', 'orderId' => 'pay20220911041647', ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function unipayQueryOrder($data)
  {
    $res = Pay::unipay()->find($data);
    return $res;
  }
  /**
   * unipayRefund
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => 'refund' . date('YmdHis'), 'origQryId' => '392209121420295251518' ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function unipayRefund($data)
  {
    $res = Pay::unipay()->refund($data);
    return $res;
  }
  /**
   * unipayCancel
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => 'cancel' . date('YmdHis'), 'origQryId' => '062209121414535249018' ]
   * @return array|Collection
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function unipayCancel($data)
  {
    $res = Pay::unipay()->cancel($data);
    return $res;
  }
  /**
   * unipayClose
   * @param array $data [ 'txnTime' => date('YmdHis'), 'txnAmt' => 1, 'orderId' => 'cancel' . date('YmdHis'), 'origQryId' => '062209121414535249018' ]
   * @return void
   * @throws ContainerException
   * @throws InvalidParamsException
   * @throws ServiceNotFoundException
   */
  public function unipayClose($data)
  {
    $this->unipayCancel($data);
  }

  public function unipayReturnCallback()
  {
    $res = Pay::unipay()->callback();
    return $res;
  }

  public function unipayNotifyCallback()
  {
    /*
    try {
      $data = Pay::unipay()->callback(); // 是的，验签就这么简单！
    } catch (\Exception $e) {
      // $e->getMessage();
    }
    */

    $res = Pay::unipay()->success();
    return $res;
  }
}
